package raochang.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import raochang.mapper.BooksMapper;
import raochang.pojo.entry.Books;
import raochang.pojo.entry.Reader;
import raochang.pojo.vo.BooksResponsVo;
import raochang.pojo.vo.BooksVo;
import raochang.service.BooksService;
import raochang.service.ReadersService;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 图书数据 服务实现类
 * </p>
 *
 * @author itheima
 */
@Service
public class BooksServiceImpl extends ServiceImpl<BooksMapper, Books> implements BooksService {
    private static final String USER_AGENT = "Mozilla/5.0";
    @Autowired
    private ReadersService readersService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importBooks(int page,String sessionId) {

        String url = "https://lib.scjyzb.cn/v1/catalog/bookBar/bookBarListQuery?page=" + page + "&pagesize=100";
        try {
            System.out.println("开始导入图书数据---------");
            sendPOST(url,sessionId);
            System.out.println("导入图书数据成功---------");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("导入图书数据失败---------");
        }
    }


    /**
     * 借书
     */
    @Override
    public void borrowBooks(List<Reader> readers,String sessionId,int num) {
        String url = "https://lib.scjyzb.cn/v1/circulation/borrowBook";
        try {
            System.out.println("开始借书---------");
            readers.forEach(reader -> {
                extracted(reader, url,sessionId,num);
            });

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("借书失败---------");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void extracted(Reader reader, String url,String sessionId,int num) {
        //查询出未借出书籍前22的书籍
        List<String> booksIds = lambdaQuery().
                eq(Books::getState, "0")
                .list()
                .stream()
                .limit(num)
                .map(Books::getBarcode)
                .collect(Collectors.toList());
        sendPostBorrowBooks(url, reader.getReaderCode(), reader.getReaderId(), booksIds,sessionId);
        //改变数据库中书籍的状态
        lambdaUpdate().in(Books::getBarcode, booksIds)
                .set(Books::getState, "1")
                .set(Books::getSaveTime,LocalDateTime.now())
                .update();
        //改变数据库中读者的借书数量
        readersService.lambdaUpdate()
                .eq(Reader::getReaderId, reader.getReaderId())
                .set(Reader::getBorrowNum, reader.getBorrowNum() + num)
                .update();

        System.out.println("借书完成---------班级code为:"+ reader.getReaderName()+reader.getReaderCode());
    }

    /**
     * 还书请求
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void returnBooks(String sessionId,int num) {
        //每天还255本
        //https://lib.scjyzb.cn/v1/circulation/returnBookCheck
        //https://lib.scjyzb.cn/v1/circulation/returnBookCheck
        String url = "https://lib.scjyzb.cn/v1/circulation/returnBook";
        //查询数据库中的书籍信息
        List<Books> books = lambdaQuery()
                .eq(Books::getState, "1")
                .list().stream().sorted(Comparator.comparing(Books::getId))
                .limit(num)
                .collect(Collectors.toList());
        System.out.println("开始还书---------");
        books.forEach(book -> {
            try {
                sendReturnPOST(url, book.getBarcode(),sessionId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            //改变数据库中书籍的状态
            lambdaUpdate().eq(Books::getBarcode, book.getBarcode())
                    .set(Books::getState, "0")
                    .set(Books::getReturnTime, LocalDateTime.now())
                    .update();
        });
        System.out.println("还书完成---------");


    }

    /**
     * 清洗数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initBooks(int i,String sessionId) {
        String url="https://lib.scjyzb.cn/v1/circulation/queryBookCirculate?page="+i+"&pagesize=100";
        try {
            System.out.println("开始清洗数据---------第"+i+"页");
            initBooksPOST(url,sessionId);
            System.out.println("数据清洗完成---------第"+i+"页");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     */
    @Override
    public void getSessionId() {
        String url="https://lib.scjyzb.net/";

    }

    /**
     * 清洗数据请求
     */
    private void initBooksPOST(String url,String sessionId) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("User-Agent", USER_AGENT);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");
        httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
        httpPost.setHeader("Connection", "keep-alive");
//        httpPost.setHeader("Content-Length", "2");
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Cookie", "orgType=2; orgId=08534; SESSION="+sessionId+"; SF_cookie_11=78087231; menuUrl=/winshare-library/school/library/org_list");
        httpPost.setHeader("Host", "lib.scjyzb.cn");
        httpPost.setHeader("Origin", "https://lib.scjyzb.cn");
        httpPost.setHeader("Referer", "https://lib.scjyzb.cn/");
        httpPost.setHeader("sec-ch-ua", "\";Not A Brand\";v=\"99\", \"Chromium\";v=\"94\"");
        httpPost.setHeader("sec-ch-ua-mobile", "?0");
        httpPost.setHeader("sec-ch-ua-platform", "Windows");
        httpPost.setHeader("Sec-Fetch-Dest", "empty");
        httpPost.setHeader("Sec-Fetch-Mode", "cors");
        httpPost.setHeader("Sec-Fetch-Site", "same-origin");
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        String jsonPayload = "{\"checkOutStartTime\":\"Invalid date\",\"checkOutEndTime\":\"Invalid date\",\"borrowState\":\"1\",\"checkOutTime\":[\"\",\"\"]}";
        HttpEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int responseCode = httpResponse.getStatusLine().getStatusCode();
        System.out.println("Response Code: " + responseCode);
        BufferedReader in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        importToDb1(response);
    }
    private void importToDb1(StringBuffer response) {
        /**
         * 清洗数据
         */
        Gson gson = new Gson();
        BooksResponsVo person = gson.fromJson(response.toString(), BooksResponsVo.class);
        List<BooksVo> rows = person.getRows();
        //判断集合是否为空
        if (!CollectionUtils.isEmpty(rows)) {
            List<String> booksCodes = rows.stream().map(BooksVo::getBarcode).collect(Collectors.toList());
            System.out.println("正在修改code值为:"+booksCodes+"中的值");
            lambdaUpdate().in(Books::getBarcode, booksCodes)
                    .set(Books::getState, "1")
                    .update();
        }
    }

    /**
     * 发送还书请求
     *
     * @param url
     * @param barcode
     * @throws Exception
     */
    private void sendReturnPOST(String url, String barcode,String sessionId) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("User-Agent", USER_AGENT);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");
        httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
        httpPost.setHeader("Connection", "keep-alive");
//        httpPost.setHeader("Content-Length", "2");
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Cookie", "orgType=2; orgId=08534; SESSION="+sessionId+"; SF_cookie_11=78087231; menuUrl=/winshare-library/school/library/org_list");
        httpPost.setHeader("Host", "lib.scjyzb.cn");
        httpPost.setHeader("Origin", "https://lib.scjyzb.cn");
        httpPost.setHeader("Referer", "https://lib.scjyzb.cn/");
        httpPost.setHeader("sec-ch-ua", "\";Not A Brand\";v=\"99\", \"Chromium\";v=\"94\"");
        httpPost.setHeader("sec-ch-ua-mobile", "?0");
        httpPost.setHeader("sec-ch-ua-platform", "Windows");
        httpPost.setHeader("Sec-Fetch-Dest", "empty");
        httpPost.setHeader("Sec-Fetch-Mode", "cors");
        httpPost.setHeader("Sec-Fetch-Site", "same-origin");
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        String jsonPayload = "{\"barcode\": \"" + barcode + "\"}";
        HttpEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        httpResponse.getStatusLine().getStatusCode();
        System.out.println("已还数据code:" + barcode);
    }

    /**
     * 发送借书请求
     *
     * @param url        请求地址
     * @param readerCode 读者code
     * @param readerIds  读者id
     * @param books      数据对象
     */
    @Async
    public void sendPostBorrowBooks(String url, String readerCode, Long readerIds, List<String> books,String sessionId) {
        books.forEach(book -> {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            // 设置请求头
            httpPost.setHeader("User-Agent", USER_AGENT);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
            httpPost.setHeader("Connection", "keep-alive");
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Cookie", "orgType=2; orgId=08534; SESSION=" + sessionId + "; SF_cookie_11=78087231; menuUrl=/winshare-library/school/library/org_list");
            httpPost.setHeader("Origin", "https://lib.scjyzb.cn");
            httpPost.setHeader("Referer", "https://lib.scjyzb.cn/");
            httpPost.setHeader("sec-ch-ua", "\"Not;A=Brand\";v=\"24\", \"Chromium\";v=\"128\"");
            httpPost.setHeader("sec-ch-ua-mobile", "?0");
            httpPost.setHeader("sec-ch-ua-platform", "Windows");
            httpPost.setHeader("Sec-Fetch-Dest", "empty");
            httpPost.setHeader("Sec-Fetch-Mode", "cors");
            httpPost.setHeader("Sec-Fetch-Site", "same-origin");
            httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
            String jsonPayload = "{\"code\": \"" + readerCode + "\", \"readerId\": " + readerIds + ", \"barcode\": \"" + book + "\"}";
            StringEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            try {
                CloseableHttpResponse execute = httpClient.execute(httpPost);
                System.out.println(execute);
                System.out.println("借出书籍code为:"+ book );
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        });


    }


    private void sendPOST(String url,String sessionId) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("User-Agent", USER_AGENT);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");
        httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
        httpPost.setHeader("Connection", "keep-alive");
//        httpPost.setHeader("Content-Length", "2");
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Cookie", "orgType=2; orgId=08534; SESSION="+sessionId+"; SF_cookie_11=78087231; menuUrl=/winshare-library/school/library/org_list");
        httpPost.setHeader("Host", "lib.scjyzb.cn");
        httpPost.setHeader("Origin", "https://lib.scjyzb.cn");
        httpPost.setHeader("Referer", "https://lib.scjyzb.cn/");
        httpPost.setHeader("sec-ch-ua", "\";Not A Brand\";v=\"99\", \"Chromium\";v=\"94\"");
        httpPost.setHeader("sec-ch-ua-mobile", "?0");
        httpPost.setHeader("sec-ch-ua-platform", "Windows");
        httpPost.setHeader("Sec-Fetch-Dest", "empty");
        httpPost.setHeader("Sec-Fetch-Mode", "cors");
        httpPost.setHeader("Sec-Fetch-Site", "same-origin");
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        String jsonPayload = "{\"state\": \"0\"}";
        StringEntity entity = new StringEntity(jsonPayload, ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        int responseCode = httpResponse.getStatusLine().getStatusCode();
        System.out.println("Response Code: " + responseCode);
        BufferedReader in = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        importToDb(response);
    }

    private void importToDb(StringBuffer response) {
        /**
         * 数据转换成接受类
         */
        Gson gson = new Gson();
        BooksResponsVo person = gson.fromJson(response.toString(), BooksResponsVo.class);
        List<BooksVo> rows = person.getRows();
        //判断集合是否为空
        if (!CollectionUtils.isEmpty(rows)) {
            rows.forEach(s -> {
                Books reader = new Books();
                BeanUtils.copyProperties(s, reader);
                save(reader);
            });
        }
    }

}
